package org.chen.scene.qdrant;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.chen.common.qdrant.QdrantAttractionData;
import org.chen.common.scene.entity.Attraction;
import org.chen.scene.utils.QdrantIdUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import java.util.*;

@Slf4j
@Service
public class QdrantHttpService implements QdrantService {

    @Value("${qdrant.http.host:http://8.219.169.114:6333}")
    private String httpHost;

    @Value("${qdrant.api-key:LZ@nKvnvG6m6gCy}")
    private String apiKey;

    @Value("${qdrant.collection-name:products}")
    private String collectionName;

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;
    private HttpHeaders headers;

    public QdrantHttpService() {
        this.restTemplate = new RestTemplate();
        this.objectMapper = new ObjectMapper();
    }

    @PostConstruct
    public void init() {
        // 设置HTTP请求头
        headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        if (apiKey != null && !apiKey.isEmpty()) {
            headers.set("api-key", apiKey);
        }

        try {
            initializeCollection(collectionName);
        } catch (Exception e) {
            log.error("初始化Qdrant集合失败", e);
        }
    }

    @Override
    public void initializeCollection(String collectionName) {
        try {
            // 检查集合是否存在
            String url = httpHost + "/collections/" + collectionName;

            try {
                HttpEntity<String> entity = new HttpEntity<>(headers);
                restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
                log.info("Qdrant集合已存在: {}", collectionName);
                return;
            } catch (Exception e) {
                log.info("集合不存在，开始创建: {}", collectionName);
            }

            // 创建集合配置（使用命名向量）
            Map<String, Object> createRequest = new HashMap<>();

            // 创建多个命名向量
            Map<String, Object> vectorsConfig = new HashMap<>();

            // 地理位置向量：经纬度，使用欧式距离
            Map<String, Object> geoVector = new HashMap<>();
            geoVector.put("size", 2);
            geoVector.put("distance", "Euclid");

            // 属性向量：visit_hours, comments, rating, hot_score，使用余弦相似度
            Map<String, Object> attrVector = new HashMap<>();
            attrVector.put("size", 4);
            attrVector.put("distance", "Cosine");

            vectorsConfig.put("geo", geoVector);
            vectorsConfig.put("attr", attrVector);

            createRequest.put("vectors", vectorsConfig);

            String requestBody = objectMapper.writeValueAsString(createRequest);
            HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);

            ResponseEntity<String> response = restTemplate.exchange(
                    httpHost + "/collections/" + collectionName,
                    HttpMethod.PUT,
                    entity,
                    String.class
            );

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("成功创建Qdrant集合: {}", collectionName);
            } else {
                log.error("创建Qdrant集合失败: {}", response.getStatusCode());
            }

        } catch (Exception e) {
            log.error("初始化Qdrant集合异常: {}", collectionName, e);
        }
    }

    @Override
    public Object saveAttractionVector(Attraction attraction) {
        if (attraction == null || attraction.getId() == null) {
            log.warn("景点数据为空，跳过向量保存");
            throw new RuntimeException("景点数据为空，无法保存向量");
        }

        try {
            // 构建向量数据
            QdrantAttractionData productData = buildQdrantAttractionData(attraction);
//            log.info("构建Qdrant景点数据: {}", productData);

            Map<String, List<Double>> vectors = productData.getVectors();

            Object pointId = attraction.getPoiId();

            // 构建请求数据
            Map<String, Object> point = new HashMap<>();
            point.put("id", pointId);
            point.put("vector", vectors);
            point.put("payload", productData.getPayload());

            Map<String, Object> upsertRequest = new HashMap<>();
            upsertRequest.put("points", Collections.singletonList(point));

            String requestBody = objectMapper.writeValueAsString(upsertRequest);
            log.info("发送到Qdrant的完整JSON: {}", requestBody);

            // 发送请求
            String url = httpHost + "/collections/" + collectionName + "/points";
            HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);

            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.PUT, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("成功保存景点向量数据: {} -> {}", attraction.getPoiId(), pointId);
            } else {
                log.error("保存景点向量数据失败: {} - {}", attraction.getPoiId(), response.getStatusCode());
            }

            return pointId;

        } catch (Exception e) {
            log.error("保存景点向量数据异常: {}", attraction.getPoiId(), e);
            throw new RuntimeException("保存景点向量数据异常: " + attraction.getPoiId(), e);
        }
    }

    @Override
    public void deleteAttractionVector(String attractionPoiId) {
        try {
            Map<String, Object> deleteRequest = new HashMap<>();

            Object pointId = QdrantIdUtils.toValidPointId(attractionPoiId);

            deleteRequest.put("points", Collections.singletonList(pointId));

            String requestBody = objectMapper.writeValueAsString(deleteRequest);

            String url = httpHost + "/collections/" + collectionName + "/points/delete";
            HttpEntity<String> entity = new HttpEntity<>(requestBody, headers);

            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);

            if (response.getStatusCode().is2xxSuccessful()) {
                log.info("成功删除景点向量数据: {}", pointId);
            } else {
                log.error("删除景点向量数据失败: {} - {}", pointId, response.getStatusCode());
            }

        } catch (Exception e) {
            log.error("删除景点向量数据异常: {}", attractionPoiId, e);
        }
    }


    /**
     * 构建Qdrant景点数据
     */
    private QdrantAttractionData buildQdrantAttractionData(Attraction attraction) {
        QdrantAttractionData data = new QdrantAttractionData();

        try {
            // 安全的类型转换，处理 BigDecimal 和 String
            double lon = attraction.getLongitude() != null ? attraction.getLongitude().doubleValue() : 0.0;
            double lat = attraction.getLatitude() != null ? attraction.getLatitude().doubleValue() : 0.0;

            // visitHours 是 String 类型，需要解析
            double visitHours = 0.0; // 默认值
            if (attraction.getVisitHours() != null && !attraction.getVisitHours().trim().isEmpty()) {
                try {
                    visitHours = Double.parseDouble(attraction.getVisitHours().trim());
                } catch (NumberFormatException e) {
                    log.warn("解析visitHours失败: {}, 使用默认值", attraction.getVisitHours());
                }
            }

            int comments = attraction.getCommentCount() != null ? attraction.getCommentCount() : 0;
            double rating = attraction.getCommentScore() != null ? attraction.getCommentScore().doubleValue() : 0.0;

            // heatScore 是 String 类型，需要解析
            double hotScore = 0.0; // 默认值
            if (attraction.getHeatScore() != null && !attraction.getHeatScore().trim().isEmpty()) {
                try {
                    hotScore = Double.parseDouble(attraction.getHeatScore().trim());
                } catch (NumberFormatException e) {
                    log.warn("解析heatScore失败: {}, 使用默认值", attraction.getHeatScore());
                }
            }

            // 按照JS代码进行归一化处理
            double visitNorm = visitHours / 10.0;
            double commentsNorm = Math.log(1 + comments) / getMaxLogComments();
            double ratingNorm = rating / 5.0;
            double hotNorm = hotScore / 10.0;

            // 创建命名向量 - 使用Map结构
            Map<String, List<Double>> vectors = new HashMap<>();

            // 地理位置向量 (2维)
            vectors.put("geo", Arrays.asList(lon, lat));

            // 属性向量 (4维)
            vectors.put("attr", Arrays.asList(visitNorm, commentsNorm, ratingNorm, hotNorm));

//            log.info("构建的命名向量 - geo: {}, attr: {}", vectors.get("geo"), vectors.get("attr"));

            data.setVectors(vectors);

            // 构建元数据
            QdrantAttractionData.QdrantMetadata payload = new QdrantAttractionData.QdrantMetadata();
            payload.setName(attraction.getPoiName() != null ? attraction.getPoiName() : attraction.getDistrictName());
            payload.setLat(lat);
            payload.setLon(lon);
            payload.setVisit_hours(visitHours);
            payload.setComments(comments);
            payload.setRating(rating);
            payload.setHot_score(hotScore);
            payload.setRegion(attraction.getDistrictName() + "周边");

            data.setPayload(payload);
            return data;

        } catch (Exception e) {
            log.error("构建景点向量数据失败: {}", attraction.getPoiId(), e);
            throw new RuntimeException("构建景点向量数据失败", e);
        }
    }

    private double getMaxLogComments() {
        // 最大评论数是1000，来算
        return 3.0;
    }

}